#!/usr/bin/env python

# Copyright 2012 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Handler for validating tokens for Attribute Providers."""

import json
import logging
from google.appengine.api.app_identity import app_identity
from base import BaseHandler
from lib import authz, utils
from lib import http
from lib.accept_content import accept_content
from lib.loggable import loggable

import model

__author__ = 'Maciej Machulak'
__maintainer__ = 'Maciej Machulak'
__email__ = 'mmachulak@google.com'

__copyright__ = 'Copyright 2012, Google Inc.'
__license__ = 'Apache License 2.0'
__version__ = '0.2'
__status__ = 'Prototype'

SIG_ALG = 'RS256'


class AttributeTokenInfoHandler(BaseHandler):
  """Handler for validating tokens for Attribute Providers."""

  @authz.api_authz_required(
      scopes=['https://www.googleapis.com/auth/streetidentity.read',
              'https://www.googleapis.com/auth/streetidentity.write'])
  @accept_content('application/x-www-form-urlencoded')
  @loggable('attribute token info')
  def post(self, *args):
    """Handles requests from APs and validates tokens."""
   
    try:

      token = self.request.get('token')
      
      if not token:

        error_response = {'error': "required",
                          'error_description': 'token required' }
        raise TokenInfoError(error_response)

      token_info_response = self._verify_encrypted_token(token)

      logging.debug('successfully obtained token info')
      self.response.set_status(200)
      self.response.headers[http.Header.content_type] = http.ContentType.json_utf8
      self.response.out.write(json.dumps(token_info_response))
      return

    except TokenInfoError as ex:

      logging.error('could not verify token')
      error_response = ex.args[0]
      self.response.set_status(400)
      self.response.headers[http.Header.content_type] = http.ContentType.json_utf8
      self.response.out.write(json.dumps(error_response))

  def _verify_encrypted_token(self, token):

    token_hash = utils.get_token_hash(token)

    authorization = model.Authorization.all().filter('token_hash = ', token_hash).get()

    if authorization:
      token_info_response = {'iss': app_identity.get_service_account_name(),
                             'aud': authorization.application.client_id,
                             'scope': authorization.attribute.id,
                             'iat': authorization.iat, 'exp': authorization.exp}
      return token_info_response

    error_response = {'error': "invalid_token",
                      'error_description': 'bad_request' }
    raise TokenInfoError(error_response)

class TokenInfoError(Exception):
  """Token Info Error raised when token could not be verified."""
  pass